//////////////////////////////////////////////////////////
// Designed by www.MCUExamples.com
// rasika0612@gmail.com
//////////////////////////////////////////////////////////

#include <p18f2520.h>

#pragma config OSC    = HS  // 10MHz Crystal, (HS oscillator)
#pragma config PBADEN = OFF // PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config PWRT	  = OFF // Power-up timer disabled (the debug mode does not work if enabled)
#pragma config BOREN  = OFF // Brown-out detector off (the debug mode does not work if enabled)
#pragma config WDT    = OFF // Watchdog timer off (the debug mode does not work if enabled)

#define segA 0x01
#define segB 0x02
#define segC 0x04
#define segD 0x08
#define segE 0x10
#define segF 0x20
#define segG 0x40
#define segDP 0x80

#define ch_0 (segA+segB+segC+segD+segE+segF)
#define ch_1 (segB+segC)
#define ch_2 (segA+segB+segG+segE+segD)
#define ch_3 (segA+segB+segG+segC+segD)
#define ch_4 (segF+segG+segB+segC)
#define ch_5 (segA+segF+segG+segC+segD)
#define ch_6 (segA+segF+segG+segC+segD+segE)
#define ch_7 (segA+segB+segC)
#define ch_8 (segA+segB+segC+segD+segE+segF+segG)
#define ch_9 (segA+segB+segC+segD+segF+segG)
#define ch_A (segA+segB+segC+segE+segF+segG)
#define ch_B (segC+segD+segE+segF+segG)
#define ch_C (segA+segD+segE+segF)
#define ch_D (segB+segC+segD+segE+segG)
#define ch_E (segA+segD+segE+segF+segG)
#define ch_F (segA+segE+segF+segG)
#define ch_N (segC+segE+segG)
#define ch_P (segA+segB+segE+segF+segG)
#define ch_S (segA+segC+segD+segF+segG)
#define ch_T (segD+segE+segF+segG)
#define ch_U (segC+segD+segE)
#define ch_R (segE+segG)
#define ch_V (segC+segD+segE)

#define KEY_EJECT	1
#define KEY_PLAY	2
#define KEY_STOP	3
#define KEY_LR		4

#define DIO_hi PORTCbits.RC0=1
#define DIO_lo PORTCbits.RC0=0
//#define dir_dio TRISCbits.TRISC0
#define DIO_output	TRISCbits.TRISC0=0
#define DIO_input	TRISCbits.TRISC0=1
#define DIO_state	PORTCbits.RC0

#define STB_hi PORTCbits.RC1=1
#define STB_lo PORTCbits.RC1=0
//#define dir_stb TRISCbits.TRISC1
#define STB_output	TRISCbits.TRISC1=0

#define CLK_hi PORTCbits.RC2=1
#define CLK_lo PORTCbits.RC2=0
//#define dir_clk TRISCbits.TRISC2
#define CLK_output	TRISCbits.TRISC2=0

#define IN		1
#define OUT		0

void delay_ms(unsigned int duration);
unsigned char is_sw1_pressed(void);
unsigned char is_sw2_pressed(void);
void TM1628_display(unsigned char ucText[]);
void TM1628_clear_display(void);
void TM1628_write_data(unsigned char wdata);
void TM1628_char_to_buff (unsigned char wdata, unsigned char pos);
void TM1628_clear_buff(void);
void TM1628_read_key (void);

//unsigned char display[16] = { ndp0, ndp1, ndp2, ndp3, ndp4, ndp5, ndp6, ndp7,
//		ndp8, ndp9, ndpA, ndpB, ndpC, ndpD, ndpE, ndpF };

unsigned char ucA[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char ucKey[5] = {0x00, 0x00, 0x00, 0x00, 0x00};

void main() {

	//unsigned char ucA[7] = {0x24, 0xA0, 0xA0, 0x3C, 0xBC, 0xBC, 0x84}; // HELLO
	//unsigned char ucA[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

	unsigned char i,a,b,c,d;

	delay_ms (255);

	ADCON1 = 0x0f;
	CMCON = 0x07;

	TRISCbits.TRISC0 = 0; // Set PortC bit 0 as output, LED1 is connected to thi pin
	TRISCbits.TRISC1 = 0; // Set PortC bit 0 as output, LED2 is connected to thi pin
	TRISCbits.TRISC2 = 0; // Set PortC bit 0 as output, LED1 is connected to thi pin
	TRISCbits.TRISC5 = 0; // Set PortC bit 0 as output, LED2 is connected to thi pin

	// all the control pins are set as output
	DIO_output;
	STB_output;
	CLK_output;

	// stb = H-device is inactive
	DIO_lo;
	STB_hi;
	CLK_lo;

	TRISAbits.TRISA2 = 1; // configure SW1 pin as input
	TRISAbits.TRISA3 = 1; // configure SW2 pin as input

	a=0;
	b=0;
	c=0;
	d=0;

	TM1628_clear_display();

	while (1) {
		
		TM1628_read_key();

		if (ucKey[0] == 0x08)	// Eject
		{
			TM1628_clear_buff();
			TM1628_char_to_buff (ch_T, 0);
			TM1628_char_to_buff (ch_U, 1);
			TM1628_char_to_buff (ch_N, 7);
			TM1628_char_to_buff (ch_E, 2);
			TM1628_char_to_buff (ch_R, 3);
			TM1628_char_to_buff (0, 4);
			TM1628_char_to_buff (0, 5);
			TM1628_display (ucA);
		}


		if (ucKey[1] == 0x01)	// Play
		{
			TM1628_clear_buff();
			TM1628_char_to_buff (ch_C, 0);
			TM1628_char_to_buff (ch_D, 1);
			TM1628_char_to_buff (0, 7);
			TM1628_char_to_buff (0, 2);
			TM1628_char_to_buff (0, 3);
			TM1628_char_to_buff (0, 4);
			TM1628_char_to_buff (0, 5);
			TM1628_display (ucA);
		}

		if (ucKey[1] == 0x02)	// Stop
		{
			TM1628_clear_buff();
			TM1628_char_to_buff (ch_S, 0);
			TM1628_char_to_buff (ch_A, 1);
			TM1628_char_to_buff (ch_T, 7);
			TM1628_char_to_buff (0, 2);
			TM1628_char_to_buff (0, 3);
			TM1628_char_to_buff (0, 4);
			TM1628_char_to_buff (0, 5);
			TM1628_display (ucA);

		}

		if (ucKey[0] == 0x10)	// L/R
		{
			
			TM1628_clear_buff();
			TM1628_char_to_buff (ch_T, 0);
			TM1628_char_to_buff (ch_V, 1);
			TM1628_char_to_buff (0, 7);
			TM1628_char_to_buff (0, 2);
			TM1628_char_to_buff (0, 3);
			TM1628_char_to_buff (0, 4);
			TM1628_char_to_buff (0, 5);
			TM1628_display (ucA);
		}

	}
}

/////////////////////////////////////////////////////////////////////////////////////////
// 	this is delay routine
// 	input: required Delay duration in mili Seconds
//	output: none
/////////////////////////////////////////////////////////////////////////////////////////

void delay_ms(unsigned int duration) // delay in miliseconds for 4.0MHZ crystal
{
	unsigned int i;
	for (; duration != 0; duration--) {
		for (i = 0; i <= 50; i++) {
			_asm
			nop
			nop
			nop
			_endasm
		}
		_asm
		nop
		nop
		_endasm
	}
}
/************************************************************************
*	void TM1628_display(unsigned char ucText[])
*	Puts the content of the specified buffer on the display
*	input: character buffer
*	output: none
************************************************************************/
void TM1628_display(unsigned char ucText[]) {
	unsigned char i;

	DIO_hi;
	CLK_hi;
	STB_hi;
	TM1628_write_data(0x03);
	STB_hi;
	TM1628_write_data(0x44);
	STB_hi;

	for (i = 0; i < 7; i++) {
		TM1628_write_data(0xC0 + (i * 2));
		TM1628_write_data(ucText[i]);
		STB_hi;
	}

	TM1628_write_data(0x8F); // display on, brightness max
	STB_hi;
}
/************************************************************************
 * 	void TM1628_clear_display ()
 * 	Clears the display by clearing the internal buffer content
 * 	input: none
 * 	output: none
 ************************************************************************/
void TM1628_clear_display () {
	unsigned char i;

	DIO_hi;
	CLK_hi;
	STB_hi;
	TM1628_write_data(0x03);
	STB_hi;
	TM1628_write_data(0x44);
	STB_hi;

	for (i = 0; i < 16; i++) {
		TM1628_write_data ( 0xC0 + i );
		TM1628_write_data ( 0x00 );
		STB_hi;
	}

	TM1628_write_data(0x80); // display on, brightness min
	STB_hi;
}

/************************************************************************
 * 	void TM1628_write_data(unsigned char wdata)
 * 	Send a single byte to the TM1628 chip
 * 	input: byte to be written
 * 	output: none
 ************************************************************************/
void TM1628_write_data(unsigned char wdata) {
	unsigned char i;
	STB_lo;
	for (i = 0; i < 8; i++) {
		CLK_lo;
		if (wdata & 0x01) {
			DIO_hi;
		} else {
			DIO_lo;
		}
		CLK_hi;
		wdata >>= 1;
	}
}

/************************************************************************
 * 	void TM1628_char_to_buff (unsigned char ucData, unsigned char ucPos)
 * 	Write a prediefined character (see #define ch_x) to the software
 * 	buffer. The character and the character position must be passed.
 * 	The new character is added to the existing buffer content
 * 	input: character data, character position
 * 	output: none
 ************************************************************************/
void TM1628_char_to_buff (unsigned char ucData, unsigned char ucPos)
{
	unsigned char i;
	unsigned char ucTemp[7];

	for (i=0; i<7; i++)
	{
		if (ucData & 0x01) {
			ucTemp[i] = 1;
		} else {
			ucTemp[i] = 0;
		}

		ucData >>= 1;
	}

	for (i=0; i<7; i++)
	{
		ucTemp[i] <<= ucPos;		// shift the character to the appropriate position
		ucA[i] += ucTemp[i];		// add to the original 
	}

}

/************************************************************************
 * 	void TM1628_clear_buff (void)
 * 	Clears the software character buffer
 * 	input: none
 * 	output: none
 ************************************************************************/
void TM1628_clear_buff (void)
{
	unsigned char i;

	for (i=0; i<7; i++)
	{
		ucA[i] = 0;
	}

}

/************************************************************************
 * 	void TM1628_read_key (void)
 * 	Reads the states of the keys connected to the TM1628. The read data
 * 	is stored in the ucKey[] array
 * 	input: none
 * 	output: none
 ************************************************************************/
void TM1628_read_key (void)
{
	unsigned char i,j;

	TM1628_write_data ( 0x42 );

	DIO_input;

	for (j=0; j<5; j++)
	{
		for (i=0; i<8; i++)
		{
			ucKey[j] = ucKey[j] >> 1;
			CLK_lo;
			CLK_hi;
			if ( DIO_state )
				ucKey[j] = ucKey[j] | 0x80;
		}
	}

	DIO_output;

	STB_hi;
}

/************************************************************************
 * 	void change_channel (unsigned char channel)
 * 	Switch to a different audio source
 * 	input: channel number 1-9
 * 	output: none
 ************************************************************************/
void change_source (unsigned char channel)
{

}

/************************************************************************
 * 	void check_signal (void)
 * 	Checks if the selected digital audio source has audio signal
 * 	Check the NVERR and /AUDIO pins of the CS8415A
 * 	input: channel number 1-9
 * 	output: 1 - valid signal, 0 - no signal
 ************************************************************************/
unsigned char check_signal (void)
{

}

/************************************************************************
 * 	void check_buttons (void)
 * 	Checks if any of the front panel buttons was pressed
 * 	input: none
 * 	output: 0 - no keypress, 1-4 - the code of the pressed button
 ************************************************************************/
unsigned char check_button(void) {

	TM1628_read_key();

	if (ucKey[0] == 0x08) // Eject
			{
		return KEY_EJECT;
	} else if (ucKey[1] == 0x01) // Play
			{
		return KEY_PLAY;
	} else if (ucKey[1] == 0x02) // Stop
			{
		return KEY_STOP;
	} else if (ucKey[0] == 0x10) // L/R
			{
		return KEY_LR;
	} else {
		return 0;
	}

}
